package com.micrometa.km.ui.components;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.dnd.DnDConstants;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.SwingUtilities;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

import com.micrometa.km.ui.components.processbar.ProcessBar;
import com.micrometa.km.ui.components.tree.FileTree;
import com.micrometa.km.ui.components.tree.FileTreeNode;
import com.micrometa.km.ui.components.tree.FileTreeNodeUtil;
import com.micrometa.km.ui.components.tree.PopupMenu;
import com.micrometa.km.util.PropertyUtil;

public class TreePanel extends JPanel implements DropTargetListener{
	private static final long serialVersionUID = 1L;
	private JTree tree;
	private PopupMenu popMenu;
	private JProgressBar aJProgressBar;

	public TreePanel() {
		new DropTarget(this, DnDConstants.ACTION_COPY_OR_MOVE, this);
		this.setLayout(new BorderLayout());
		File root = new File(PropertyUtil.repositoryRoot());
		this.tree = new FileTree(FileTreeNodeUtil
				.getFileTreeNodesParentSub(root));
		this.tree.setDragEnabled(true);
		JScrollPane jsp = new JScrollPane(this.tree);
		this.add(jsp, BorderLayout.CENTER);
		aJProgressBar = new JProgressBar(0, 1);
		aJProgressBar.setStringPainted(true);
		aJProgressBar.setVisible(false);
		this.add(aJProgressBar, BorderLayout.SOUTH);
		popMenu = new PopupMenu(this.tree);

		this.tree.addMouseListener(new MouseAdapter() {
			public void mousePressed(MouseEvent e) {
				if (SwingUtilities.isRightMouseButton(e)) {// e.isPopupTrigger()
					TreePath path = tree.getPathForLocation(e.getX(), e.getY()); // 关键是这个方法的使用
					tree.setSelectionPath(path);
					if (path == null) {
						popMenu.getReItem().setEnabled(false);
						popMenu.getEditItem().setEnabled(false);
						popMenu.getDelItem().setEnabled(false);
					} else {
						popMenu.getReItem().setEnabled(true);
						popMenu.getDelItem().setEnabled(true);
						popMenu.getAddItem().setEnabled(true);
						popMenu.getEditItem().setEnabled(true);
					}
					popMenu.show(tree, e.getX(), e.getY());
				}
			}

			public void mouseClicked(MouseEvent e) {
				TreePath path = tree.getPathForLocation(e.getX(), e.getY()); // 关键是这个方法的使用
				if (path == null)
					return;
				if (e.getClickCount() == 2) {
					//double click on tree node
					FileTreeNode tar = (FileTreeNode) 
					tree.getLastSelectedPathComponent();
					//path.getLastPathComponent();
					File tf = (File) tar.getFile();
					if (tf.isFile()) {
						try {
							// TODO:Unix, Linux, Mac
							// it is Windows run
							String[] cmd = new String[5];
							cmd[0] = "cmd";
							cmd[1] = "/c";
							cmd[2] = "start";
							cmd[3] = " ";
							cmd[4] = tf.getAbsolutePath();
							Runtime.getRuntime().exec(cmd);
						} catch (IOException e1) {
							// TODO Auto-generated catch block
							e1.printStackTrace();
						}
					} else if (tf.isDirectory()) {
						// System.out.println(tar.getChildCount());
						if (tar.getChildCount() == 0) {
							for (FileTreeNode n : FileTreeNodeUtil
									.getFileTreeNodesSub(tf)) {
								tar.add(n);
							}
							tree.expandPath(path);
							tree.updateUI();
						}
					}
				}
			}
		});
	}

	@Override
	public void dragEnter(DropTargetDragEvent dtde) {
		
	}

	@Override
	public void dragExit(DropTargetEvent dte) {
		// TODO Auto-generated method stub

	}

	@Override
	public void dragOver(DropTargetDragEvent dtde) {
		//TODO 位置不准，当tree滑动时
		Point ap = dtde.getLocation(); // get event point
		int x = (int) ap.getX();
		int y = (int) ap.getY();
		TreePath path = tree.getPathForLocation(x, y);
		if (path == null)
			return;
		FileTreeNode tar = (FileTreeNode) path.getLastPathComponent();
		File tf = (File) tar.getFile();
		if (tf.isDirectory()) {
			if (tar.getChildCount() == 0) {
				for (FileTreeNode n : FileTreeNodeUtil
						.getFileTreeNodesSub(tf)) {
					tar.add(n);
				}
			}
			tree.expandPath(path);
			tree.updateUI();
		}
		//tree.setSelectionPath(path);
	}

	@Override
	public void drop(DropTargetDropEvent dtde) {
		dtde.acceptDrop(DnDConstants.ACTION_COPY);
		// get drag source file
		Transferable transferable = dtde.getTransferable();
		DataFlavor[] flavors = transferable.getTransferDataFlavors();
		// get target tree node
		Point ap = dtde.getLocation(); // get event point
		int x = (int) ap.getX();
		int y = (int) ap.getY();
		TreePath tp = tree.getPathForLocation(x, y);
		FileTreeNode parnode = null;
		// tree.setSelectionPath(tp);
		// File f = null;
		List<File> fileList = new ArrayList<File>();
		for (int i = 0; i < flavors.length; i++) {
			DataFlavor d = flavors[i];
			// System.out.println(d.getMimeType());
			try {
				if (d.equals(DataFlavor.javaFileListFlavor)) {
					fileList = (List<File>) transferable.getTransferData(d);
					// f = fileList.get(0);
					// if (!f.canExecute()) {
					// JOptionPane.showMessageDialog(this, "文件‘" + f.getName()
					// + "’拒绝访问");
					// return;
					// }
				} else if (d.equals(DataFlavor.stringFlavor)) {
					//进入这里表示tree内部拖拽,由FileTree.DJTreeTransferable决定
					//TODO 无法更新被移动的treenode
					 FileTreeNode sourceNode = (FileTreeNode) transferable.getTransferData(d);
//					 System.out.println(sourceNode.getFile().getName());
					 File sourceFile=sourceNode.getFile();
					 if (tp != null) {
							// get drop tree node with treepath
							FileTreeNode no1 = (FileTreeNode) tp.getLastPathComponent();
							File tf = (File) no1.getFile();
							if (tf.isDirectory())
								parnode = no1;
							else
								parnode = (FileTreeNode) no1.getParent();
							//cut files to new path
							if (sourceFile != null && sourceFile.canExecute()) {
								String path=parnode.getFile().getAbsolutePath()+"/"+sourceFile.getName();
								//TODO delete syso
//								System.out.println(sourceFile.getName());
//								System.out.println(path);
								
								if(sourceFile.renameTo(new File(path))){
									DefaultTreeModel model=(DefaultTreeModel) tree.getModel();
									//remove source treepath
									File sf=((FileTreeNode)sourceNode.getParent()).getFile();
									FileTreeNode sourcen = FileTreeNodeUtil.getFileTreeNodes(sf);
									model.insertNodeInto(sourcen,
											(MutableTreeNode) sourceNode.getParent(), sourceNode.getParent()
											.getIndex(sourceNode));
									model.removeNodeFromParent(sourceNode);
									//refresh target treepath
									FileTreeNode tarn = FileTreeNodeUtil.getFileTreeNodes(parnode
											.getFile());
									model.insertNodeInto(tarn,
											(MutableTreeNode) parnode.getParent(), parnode.getParent()
											.getIndex(parnode));
									model.removeNodeFromParent(parnode);
									//expend
									tree.expandPath(new TreePath(((DefaultTreeModel) tree.getModel())
											.getPathToRoot(tarn)));
									tree.updateUI();
								}
							}
					}
				} 
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		
		if (tp != null) {
			// get drop tree node with treepath
			FileTreeNode no1 = (FileTreeNode) tp.getLastPathComponent();
			File tf = (File) no1.getFile();
			if (tf.isDirectory())
				parnode = no1;
			else
				parnode = (FileTreeNode) no1.getParent();
			//copy or cut files with processbar
			if (fileList != null && fileList.size() > 0) {
				
				ProcessBar stepper = new ProcessBar(aJProgressBar, fileList, parnode
						.getFile());
				stepper.setTree(tree, parnode);
				stepper.start();
			}
		}else{
			//TODO if path==null, node is root
			//parnode=(FileTreeNode) tree.getModel().getRoot();
			JOptionPane.showMessageDialog(null, "请先点击鼠标右键“添加”文件夹，再将文件拖入文件夹！");
		}
		dtde.dropComplete(true);
	}

	@Override
	public void dropActionChanged(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub

	}

}
